//
// Created by Administrator on 2024/12/10.
//

#include <libdaq/device/DAQ125/DAQ125.h>
#include <libdaq/device/DAQ206/DAQ206.h>
#include <libdaq/device/DAQ207/DAQ207.h>
#include "libdaq/utils/wrapper_util.h"
#include "usb_server.h"

namespace libdaq::backend
{

enum class DeviceType {
  DeviceType_DAQ217,
  DeviceType_DAQ216,
  DeviceType_DAQ207,
  DeviceType_DAQ206,
  DeviceType_DAQ125,
};

DLL_EXPORT uint32_t *CALL_FUNCTION USBServer_New(const DeviceType device_type);
DLL_EXPORT void CALL_FUNCTION USBServer_Delete(uint32_t *handle);
DLL_EXPORT void CALL_FUNCTION USBServer_StartSearch(uint32_t *handle);
DLL_EXPORT uint32_t* CALL_FUNCTION USBServer_GetBusNumbers(uint32_t *handle, uint8_t& bus_count);
DLL_EXPORT uint32_t* CALL_FUNCTION USBServer_GetDeviceAddresses(uint32_t *handle, uint8_t bus_number, uint8_t& device_count);
DLL_EXPORT uint32_t *CALL_FUNCTION USBServer_GetClient(uint32_t *handle, uint8_t bus_number, uint8_t device_address);


uint32_t *USBServer_New(const DeviceType device_type) {
  USBOption option;
  if (device_type == DeviceType::DeviceType_DAQ217) {
    option = device::DAQ217::GetUSBOption();
  }else if (device_type == DeviceType::DeviceType_DAQ216) {
    option = device::DAQ216::GetUSBOption();
  }else if (device_type == DeviceType::DeviceType_DAQ207) {
    option = device::DAQ207::GetUSBOption();
  }else if (device_type == DeviceType::DeviceType_DAQ206) {
    option = device::DAQ206::GetUSBOption();
  }else if (device_type == DeviceType::DeviceType_DAQ125) {
    option = device::DAQ125::GetUSBOption();
  }else{
    return nullptr;
  }

  auto server = new LockzhinerUSBServer(option);
  return reinterpret_cast<uint32_t *>(server);
}


void USBServer_Delete(uint32_t *handle) {
  auto server = reinterpret_cast<LockzhinerUSBServer*>(handle);
  delete server;
  server = nullptr;
}

void USBServer_StartSearch(uint32_t *handle) {
  auto server = reinterpret_cast<LockzhinerUSBServer*>(handle);
  server->StartSearch();
}

uint32_t* USBServer_GetBusNumbers(uint32_t *handle, uint8_t& bus_count) {
  auto server = reinterpret_cast<LockzhinerUSBServer*>(handle);
  auto temp = server->GetBusNumbers();
  bus_count = temp.size();
  auto bus_numbers = new uint32_t[bus_count];
  for (int i = 0; i < bus_count; i++) {
    bus_numbers[i] = temp[i];
  }
  return bus_numbers;
}

uint32_t* USBServer_GetDeviceAddresses(uint32_t *handle, uint8_t bus_number, uint8_t& device_count)
{
  auto server = reinterpret_cast<LockzhinerUSBServer*>(handle);
  auto temp = server->GetDeviceAddresses(bus_number);
  device_count = temp.size();
  auto device_addresses = new uint32_t[device_count];
  for (int i = 0; i < device_count; i++) {
    device_addresses[i] = temp[i];
  }
  return device_addresses;
}


uint32_t *USBServer_GetClient(uint32_t *handle, uint8_t bus_number, uint8_t device_address)
{
  auto server = reinterpret_cast<LockzhinerUSBServer*>(handle);
  auto client = server->GetClient(bus_number, device_address);
  return reinterpret_cast<uint32_t *>(client);
}


} // namespace libdaq::backend
